package com.heima.comment.service.impl;

import com.heima.apis.user.IUserClient;
import com.heima.comment.service.ApCommentHotService;
import com.heima.comment.service.ApCommentService;
import com.heima.model.comment.dtos.CommentDto;
import com.heima.model.comment.dtos.CommentLikeDto;
import com.heima.model.comment.dtos.CommentSaveDto;
import com.heima.model.comment.pojos.ApComment;
import com.heima.model.comment.pojos.ApCommentLike;
import com.heima.model.comment.vos.CommentVo;
import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.utils.common.ThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class ApCommentServiceImpl implements ApCommentService {

    @Autowired
    private IUserClient userClient;

    @Autowired
    private MongoTemplate mongoTemplate;

    @Override
    public ResponseResult save(CommentSaveDto dto) {

        //1. 判断参数不能为空
        if(dto.getArticleId()==null || StringUtils.isBlank(dto.getContent())){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2. 判断用户是否存在
        Integer userId = ThreadLocalUtil.getUserId();
        ApUser apUser = userClient.findOne(userId); //注意：一定要在user服务里放行这个feign接口的请求路径
        if(apUser==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "用户不存在，无法评论");
        }

        //TODO 3. 判断文章是否存在

        //4. 判断评论内容字数是否超限140字
        if(dto.getContent().length()>140){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }

        //TODO 5. 评论内容安全过滤

        //6. 保存评论数据到MongoDB集合里
        ApComment apComment = new ApComment();
        apComment.setUserId(userId); //评论的用户ID
        apComment.setUserName(apUser.getName()); //评论的用户名
        apComment.setType(0);//内容类型：0表示文章
        apComment.setObjectId(dto.getArticleId());//文章id
        apComment.setContent(dto.getContent());//评论的内容
        apComment.setImage(apUser.getImage());///评论的用户头像地址
        apComment.setLikes(0);//点赞数量
        apComment.setReply(0);//回复数量
        apComment.setFlag(0);//评论标识：0表示普通评论
        apComment.setCreatedTime(new Date());//创建时间
        apComment.setUpdatedTime(new Date());//更新时间

        mongoTemplate.save(apComment);
        return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
    }

    @Autowired
    private ApCommentHotService apCommentHotService;

    @Override
    public ResponseResult like(CommentLikeDto dto) {
        //1.判断参数是否为空
        if(StringUtils.isBlank(dto.getCommentId()) || dto.getOperation()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2.判断评论是否存在  ap_comment
        ApComment apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        if(apComment==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST, "评论不存在无法操作");
        }

        //3.查询评论的点赞记录 ap_comment_like
        Integer userId = ThreadLocalUtil.getUserId();
        ApCommentLike apCommentLike = mongoTemplate.findOne(Query.query(Criteria.where("userId").is(userId)
                .and("commentId").is(dto.getCommentId())), ApCommentLike.class);

        //3.1 点赞不存在的处理
        if(apCommentLike==null){
            //3.1.1 判断是否取消点赞
            if(dto.getOperation()==1){
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "点赞记录不存在无法取消点赞");
            }

            //3.1.2 更新评论的点赞数+1  ap_comment
            mongoTemplate.findAndModify(Query.query(Criteria.where("id").is(dto.getCommentId())),
                    new Update().inc("likes",1).set("updatedTime",new Date()),
                    ApComment.class);

            //3.1.3 新增点赞记录   ap_comment_like
            apCommentLike = new ApCommentLike();
            apCommentLike.setUserId(userId); //用户id
            apCommentLike.setCommentId(dto.getCommentId());//评论id
            apCommentLike.setOperation(dto.getOperation());//操作类型 0-点赞 1-取消点赞
            apCommentLike.setCreatedTime(new Date());//创建时间
            apCommentLike.setUpdatedTime(new Date());//更新时间
            mongoTemplate.save(apCommentLike);
        } else {
            //3.2 点赞记录存在的处理
            //3.2.1 判断是否重复点赞
            if(dto.getOperation()==0 && apCommentLike.getOperation()==0){
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "无需重复点赞");
            }

            //3.2.2 判断是否重复取消点赞
            if(dto.getOperation()==1 && apCommentLike.getOperation()==1){
                return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID, "无需重复取消点赞");
            }

            //3.2.3 如果是点赞，则更新评论的点赞数+1  ap_comment
            if(dto.getOperation()==0){
                mongoTemplate.findAndModify(Query.query(Criteria.where("id").is(dto.getCommentId())),
                        new Update().inc("likes",1).set("updatedTime",new Date()),
                        ApComment.class);
            } else {
                //3.2.4 如果是取消点赞，则更新评论的点赞数-1 ap_comment
                mongoTemplate.findAndModify(Query.query(Criteria.where("id").is(dto.getCommentId())),
                        new Update().inc("likes",-1).set("updatedTime",new Date()),
                        ApComment.class);
            }

            //3.2.5 修改点赞记录的操作类型 ap_comment_like
            apCommentLike.setOperation(dto.getOperation());//操作类型  0-点赞 1-取消点赞
            apCommentLike.setUpdatedTime(new Date());//更新时间
            mongoTemplate.save(apCommentLike);
        }

        //4.查询最新点赞数并响应
        apComment = mongoTemplate.findById(dto.getCommentId(), ApComment.class);
        Map map = new HashMap();
        map.put("likes",apComment.getLikes());//最新点赞数

        //5.异步计算热点评论（条件限制：点赞后 且 是普通评论 且点赞数大于5）
        if(dto.getOperation()==0 && apComment.getFlag()==0 && apComment.getLikes()>5){
            apCommentHotService.computeHotComment(apComment);
        }

        return ResponseResult.okResult(map);
    }


    @Override
    public ResponseResult list(CommentDto dto) {
        int size = 10;

        //1.判断参数是否为空
        if(dto.getArticleId()==null || dto.getMinDate()==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_REQUIRE);
        }

        //2.根据是否首页请求决定查询评论列表
        List<ApComment> apCommentList = new ArrayList<>();
        //2.1 首页请求，则查询热点评论列表+普通评论列表
        if(dto.getIndex()==1){
            //查询热点评论列表（条件：type、objectId、createdTime、flag 结果：likes倒序 限制5条） ap_comment
            List<ApComment> apCommentHotList = mongoTemplate.find(Query.query(Criteria.where("type").is(0)
                                    .and("objectId").is(dto.getArticleId())
                                    .and("createdTime").lt(dto.getMinDate())
                                    .and("flag").is(1)
                            )
                            .with(Sort.by(Sort.Direction.DESC, "likes")).limit(5),
                    ApComment.class);
            apCommentList.addAll(apCommentHotList);


            //查询剩余普通评论列表（条件：type、objectId、createdTime、flag 结果：createdTime倒序 限制条数=10-热点评论列表实际数量） ap_comment
            List<ApComment> apCommentCommonList = mongoTemplate.find(Query.query(Criteria.where("type").is(0)
                                    .and("objectId").is(dto.getArticleId())
                                    .and("createdTime").lt(dto.getMinDate())
                                    .and("flag").is(0)
                            )
                            .with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size-apCommentHotList.size()),
                    ApComment.class);
            apCommentList.addAll(apCommentCommonList);
        } else {
            //2.2 非首页请求，则查询普通评论列表（条件：type、objectId、createdTime、flag 结果：createdTime倒序 限制10条） ap_comment
            apCommentList = mongoTemplate.find(Query.query(Criteria.where("type").is(0)
                                    .and("objectId").is(dto.getArticleId())
                                    .and("createdTime").lt(dto.getMinDate())
                                    .and("flag").is(0)
                            )
                            .with(Sort.by(Sort.Direction.DESC, "createdTime")).limit(size),
                    ApComment.class);

        }

        //3.如果是游客，则直接响应评论列表数据
        Integer userId = ThreadLocalUtil.getUserId();
        if(userId==0){
            return ResponseResult.okResult(apCommentList);
        }

        //4.如果是正常用户，则标识出被用户点赞过的评论数据

        //4.1 获取评论id列表
        List<String> commentIdList = apCommentList.stream().map(ApComment::getId).collect(Collectors.toList());

        //4.2 查询点赞记录列表（条件：userId、commentId、opeartion） ap_comment_like
        List<ApCommentLike> apCommentLikeList = mongoTemplate.find(Query.query(Criteria.where("userId").is(userId)
                .and("commentId").in(commentIdList)
                .and("operation").is(0)
        ), ApCommentLike.class);

        //4.3 筛选出评论列表中具体被点赞的评论并标识为已点赞
        List<CommentVo> commentVoList = new ArrayList<>();
        for (ApComment apComment : apCommentList) {

            CommentVo commentVo = new CommentVo();
            BeanUtils.copyProperties(apComment,commentVo);

            long count = apCommentLikeList.stream().filter(x -> x.getCommentId().equals(apComment.getId())).count();
            if(count>0){ //如果有点赞记录的评论ID等于正在遍历的评论的ID，说明这个评论就被当前用户点赞过，则需要标识出来
                commentVo.setOperation(0);
            }

            commentVoList.add(commentVo);
        }

        //4.4 响应带有点赞标识的评论列表数据
        return ResponseResult.okResult(commentVoList);
    }
}
